package com.yimu.ymblog.admin.service.impl;

import cn.hutool.core.bean.BeanUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.yimu.ymblog.admin.service.AdminUserService;
import com.yimu.ymblog.common.constant.RedisConstants;
import com.yimu.ymblog.common.domain.admin.vo.user.*;
import com.yimu.ymblog.common.domain.dos.UserDO;
import com.yimu.ymblog.common.domain.dos.UserInfoDO;
import com.yimu.ymblog.common.domain.dos.UserRoleDO;
import com.yimu.ymblog.common.domain.mapper.UserInfoMapper;
import com.yimu.ymblog.common.domain.mapper.UserMapper;
import com.yimu.ymblog.common.domain.mapper.UserRoleMapper;
import com.yimu.ymblog.common.enums.LoginTypeEnum;
import com.yimu.ymblog.common.enums.ResponseCodeEnum;
import com.yimu.ymblog.common.exception.BizException;
import com.yimu.ymblog.common.service.EmailService;
import com.yimu.ymblog.common.service.RedisService;
import com.yimu.ymblog.common.utils.PageResponse;
import com.yimu.ymblog.common.utils.Response;
import org.apache.commons.lang3.ObjectUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpStatus;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.client.RestTemplate;

import javax.mail.MessagingException;
import java.time.LocalDateTime;
import java.util.Map;
import java.util.Objects;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

@Service
public class AdminUserServiceImpl implements AdminUserService {

    @Autowired
    private UserMapper userMapper;
    @Autowired
    private PasswordEncoder passwordEncoder;
    @Autowired
    private RedisService redisService;
    @Autowired
    private UserInfoMapper userInfoMapper;
    @Autowired
    private UserRoleMapper userRoleMapper;
    @Autowired
    private EmailService emailService;
    @Autowired
    private RestTemplate restTemplate;


    /**
     * 修改密码
     * @param updateAdminUserPasswordReqVO
     * @return
     */
    @Override
    public Response updatePassword(UpdateAdminUserPasswordReqVO updateAdminUserPasswordReqVO) {
    	// 拿到用户名、原密码、新密码
        String username = updateAdminUserPasswordReqVO.getUsername();
        String password = updateAdminUserPasswordReqVO.getPassword();
        String newPassword = updateAdminUserPasswordReqVO.getNewPassword();

        // 先判断用户名和原密码是匹配
        UserDO userDO = userMapper.selectOne(new LambdaQueryWrapper<UserDO>().eq(UserDO::getUsername, username));

        if (ObjectUtils.isEmpty(userDO)) {
            return Response.fail(ResponseCodeEnum.USERNAME_NOT_FOUND);
        }

        // 拿到数据库中对应用户名的密码解密后进行比对
        boolean matches = passwordEncoder.matches(password, userDO.getPassword());
        if (!matches) {
            return Response.fail(ResponseCodeEnum.PASSWORD_IS_NOT_CORRECT);
        }

        // 如果匹配则执行修改密码操作

        // 加密密码
        String encodePassword = passwordEncoder.encode(newPassword);

        // 更新到数据库
        int count = userMapper.updatePasswordByUsername(username, encodePassword);

        return count == 1 ? Response.success() : Response.fail(ResponseCodeEnum.USERNAME_NOT_FOUND);
    }


    /**
     * 获取当前登录用户信息
     * @return
     */
    @Override
    public Response findUserInfo() {
        // 获取存储在 ThreadLocal 中的用户信息
        Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
        // 拿到用户名
        String username = authentication.getName();
        // 根据用户名查询用户表
        UserDO userDO = userMapper.selectOne(new LambdaQueryWrapper<UserDO>().eq(UserDO::getUsername, username));
        // 根据用户id查用户信息表
        UserInfoDO userInfoDO = userInfoMapper.selectOne(new LambdaQueryWrapper<UserInfoDO>().eq(UserInfoDO::getUserId, userDO.getId()));
        if (ObjectUtils.isEmpty(userInfoDO)) {
            throw new BizException(ResponseCodeEnum.USERINFO_NOT_FOUND);
        }
        FindUserInfoRspVO findUserInfoRspVO = BeanUtil.toBean(userInfoDO, FindUserInfoRspVO.class);
        findUserInfoRspVO.setUsername(username);
        return Response.success(findUserInfoRspVO);
    }

    /**
     * 邮箱注册
     *
     * @param emailRegisterReqVO
     * @return
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public Response emailRegister(EmailRegisterReqVO emailRegisterReqVO) {
        // 在redis中校验验证码是否有效
        checkCode(emailRegisterReqVO.getEmail(), emailRegisterReqVO.getCode());
        // 查询邮箱在数据库中是否存在
        LambdaQueryWrapper<UserInfoDO> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(UserInfoDO::getEmail, emailRegisterReqVO.getEmail());
        UserInfoDO userInfoDO = userInfoMapper.selectOne(queryWrapper);
        if (ObjectUtils.isNotEmpty(userInfoDO)) {
            throw new BizException(ResponseCodeEnum.ERROR_EXCEPTION_EMAIL_IS_EXISTED);
        }
        // 保存账号信息
        UserDO user = UserDO.builder()
                .username(emailRegisterReqVO.getEmail())
                .password(passwordEncoder.encode(emailRegisterReqVO.getPassword()))
                .createTime(LocalDateTime.now())
                .updateTime(LocalDateTime.now())
                .build();
        userMapper.insert(user);
        // 保存用户信息
        UserInfoDO userInfoDO1 = UserInfoDO.builder()
                .nickname(emailRegisterReqVO.getNickname())
                .email(emailRegisterReqVO.getEmail())
                .userId(user.getId())
                .avatar(getAvater(emailRegisterReqVO.getEmail()))
                .loginType(LoginTypeEnum.getType("email"))
                .createTime(LocalDateTime.now())
                .updateTime(LocalDateTime.now())
                .build();
        userInfoMapper.insert(userInfoDO1);
        // 保存用户角色
        UserRoleDO userRoleDO = UserRoleDO.builder()
                .username(emailRegisterReqVO.getEmail())
                .role("ROLE_VISITOR")
                .createTime(LocalDateTime.now())
                .build();
        userRoleMapper.insert(userRoleDO);

        // 注册成功后，要主动删除redis中的验证码
        redisService.deleteObject(RedisConstants.EMAIL_CODE + emailRegisterReqVO.getEmail());

        return Response.success();
    }

    /**
     * 发送邮箱验证码
     *
     * @param email
     * @return
     */
    @Override
    public Response sendEmailCode(String email, Long type) {
        // 1 注册   2 忘记密码
        if (type == 2) {
            // 如果是忘记密码需要去修改密码，需要先判断当前邮箱是否存在
            if (userMapper.selectCount(new LambdaQueryWrapper<UserDO>().eq(UserDO::getUsername, email)) == 0) {
                throw new BizException(ResponseCodeEnum.ERROR_EXCEPTION_EMAIL_IS_NOT_EXISTED);
            }
        }
        try {
            emailService.sendCode(email);
            return Response.success();
        } catch (MessagingException e) {
            // 抛出发送邮箱验证码失败
            throw new BizException(ResponseCodeEnum.ERROR_EXCEPTION_SEND_EMAIL_CODE);
        }
    }

    /**
     * 忘记密码
     *
     * @param emailForgetPasswordReqVO
     * @return
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public Response forgetPassword(EmailForgetPasswordReqVO emailForgetPasswordReqVO) {
        checkCode(emailForgetPasswordReqVO.getEmail(), emailForgetPasswordReqVO.getCode());
        UserDO userDO = UserDO.builder()
                .password(passwordEncoder.encode(emailForgetPasswordReqVO.getPassword()))
                .build();
        userMapper.update(userDO, new LambdaQueryWrapper<UserDO>().eq(UserDO::getUsername, emailForgetPasswordReqVO.getEmail()));
        return Response.success();
    }

    /**
     * 获取用户分页列表
     *
     * @param findUserPageListReqVO
     * @return
     */
    @Override
    public PageResponse findUserPageList(FindUserPageListReqVO findUserPageListReqVO) {
        // 获取当前页、以及每页需要展示的数据数量
        Long current = findUserPageListReqVO.getCurrent();
        Long size = findUserPageListReqVO.getSize();
        String nickname = findUserPageListReqVO.getNickname();
        Integer status = findUserPageListReqVO.getStatus();

        IPage<FindUserPageListRspVo> page = new Page<>(current, size);

        IPage<FindUserPageListRspVo> findUserPageListRspVoIPage = userInfoMapper.selectUserList(page, nickname, status);

        return PageResponse.success(findUserPageListRspVoIPage, findUserPageListRspVoIPage.getRecords());

//
//        userInfoDOPage.get
//
//
//
//        Page<FindUserPageListReqVO> findUserPageListReqVO = userInfoMapper.selectPageList(current, size, nickname, status);
//        List<UserInfoDO> userInfoDOS = userInfoDOPage.getRecords();
//
//        List<FindUserPageListRspVo> vos = null;
//        if(!CollectionUtil.isEmpty(userInfoDOS)) {
//            vos = userInfoDOS.stream()
//                    .map(userInfoDO -> {
//                        // 根据查询用户角色
//                        List<UserRoleDO> userRoleDOS = userRoleMapper.selectByUsername(userInfoDO.getEmail());
//                        return FindUserPageListRspVo.builder()
//                                .id(userInfoDO.getId())
//                                .userId(userInfoDO.getUserId())
//                                .avatar(userInfoDO.getAvatar())
//                                .nickname(userInfoDO.getNickname())
//                                .login_type(userInfoDO.getLoginType())
//                                .roleList(userRoleDOS)
//                                .ipAddress(userInfoDO.getIpAddress())
//                                .ipSource(userInfoDO.getIpSource())
//                                .os(userInfoDO.getOs())
//                                .browser(userInfoDO.getBrowser())
//                                .createTime(userInfoDO.getCreateTime())
//                                .lastLoginTime(userInfoDO.getLastLoginTime())
//                                .status(userInfoDO.getStatus())
//                                .build();
//                    }).collect(Collectors.toList());
//        }
//        return PageResponse.success(userInfoDOPage, vos);
    }

    /**
     * 改变用户状态
     *
     * @param updateUserStatusReqVO
     * @return
     */
    @Override
    public Response changeUserStatus(UpdateUserStatusReqVO updateUserStatusReqVO) {
        Long id = updateUserStatusReqVO.getId();
        Long userId = updateUserStatusReqVO.getUserId();
        Integer status = updateUserStatusReqVO.getStatus();
//        Boolean sta = updateUserStatusReqVO.getStatus();
//        Integer status = null;
//        if (sta) {
//            // 如果禁用
//            status = 1;
//        } else {
//            // 如果没禁用
//            status = 0;
//        }
        // 更新用户表
        userMapper.updateById(UserDO.builder().id(userId).status(status).build());
        return Response.success();
    }

    /**
     * 校验邮箱验证码是否合法
     * @param email
     * @param code
     * @return
     */
    public Boolean checkCode(String email, String code) {
        //校验邮箱验证码 判断redis中是否存在验证码
        boolean b = redisService.hasKey(RedisConstants.EMAIL_CODE + email);
        if (!b) {
            throw new BizException(ResponseCodeEnum.ERROR_EXCEPTION_MOBILE_CODE);
        }
        // 如果验证码存在，则判断验证码是否一致
        String emailCode = (String) redisService.getCacheObject(RedisConstants.EMAIL_CODE + email);
        if (!code.equals(emailCode)) {
            throw new BizException(ResponseCodeEnum.ERROR_EXCEPTION_MOBILE_CODE);
        }
        return true;
    }

    /**
     * 获取用户头像，如果是QQ邮箱注册，就获取QQ头像，如果是其他邮箱注册，就设置个默认头像
     * @param email
     * @return
     */
    public String getAvater(String email) {
        String qq = "";
        Pattern pattern = Pattern.compile("^(\\d+)@qq\\.com$");
        Matcher matcher = pattern.matcher(email);
        if (matcher.matches()) {
            qq =  matcher.group(1);
        } else {
            return "https://img.ymblog.top/ymblog/defaultAvatar.jpg";
        }
        // 请求第三方接口
        String url = String.format("https://api.qjqq.cn/api/qqinfo?qq=%s", qq);
        // 调用接口，获取接口返回的json字符串
        String result = restTemplate.getForObject(url, String.class);

        // 解析响参 通过ObjectMapper解析Json字符串为Map
        ObjectMapper objectMapper = new ObjectMapper();
        try {
            Map<String, Object> map = objectMapper.readValue(result, Map.class);
            if (Objects.equals(map.get("code"), HttpStatus.OK.value())) {
                String imgurl = String.valueOf(map.get("imgurl"));

                return imgurl;
            }
            return "";
        } catch (JsonProcessingException e) {
            throw new RuntimeException(e);
        }
    }

}